package com.kun.companion.core.context.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.text.NamingCase;
import com.kun.companion.core.AbstractApplication;
import com.kun.companion.core.AbstractController;
import com.kun.companion.core.context.ContextService;
import com.kun.companion.core.context.annotation.InjectBean;
import com.kun.companion.core.context.factory.SingletonContextFactory;
import com.kun.companion.core.exception.Assert;
import com.kun.companion.core.exception.BizException;
import com.kun.companion.core.util.ComUtil;
import com.kun.companion.core.util.NewClassGraphUtil;
import javafx.fxml.FXMLLoader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Field;
import java.net.URL;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;

/**
 * 支持循环依赖的窗口单例工厂
 * <p>
 * 采用二级缓存机制解决循环依赖问题：
 * 1. 一级缓存（MAP）：存储完全初始化的实例
 * 2. 二级缓存（EARLY_SINGLETON_MAP）：存储半成品实例用于依赖注入
 * </p>
 *
 * @author gzc
 * @since 2025/2/3
 */
public class StageSingletonContext implements SingletonContextFactory<Class<? extends AbstractController>, AbstractController> {
    private static final Logger log = LoggerFactory.getLogger(StageSingletonContext.class);

    /**
     * 一级缓存：完全初始化的实例（线程安全）
     */
    private static final Map<Class<? extends AbstractController>, AbstractController> MAP = new ConcurrentHashMap<>(256);
    /**
     * 二级缓存：提前暴露的半成品实例（解决循环依赖）
     */
    private static final Map<Class<? extends AbstractController>, AbstractController> EARLY_SINGLETON_MAP = new ConcurrentHashMap<>(256);
    /**
     * FXML资源加载策略
     */
    private static Function<String, URL> loadFunction;
    /**
     * 应用入口类引用
     */
    private static Class<? extends AbstractApplication> loader;

    @Override
    public void init(List<String> packagePathList, Class<? extends AbstractApplication> loader, Function<String, URL> loadFunction) {
        StageSingletonContext.loadFunction = loadFunction;
        StageSingletonContext.loader = loader;
    }

    @Override
    public int order() {
        // 设置低优先级，确保依赖的BeanContext先初始化
        return 99;
    }

    @Override
    public AbstractController get(Class<? extends AbstractController> key) {
        return getInstance(key);
    }

    @Override
    public void put(Class<? extends AbstractController> key, AbstractController value) {
    }

    @Override
    public void remove(Class<? extends AbstractController> key) {
        removeInstance(key);
    }

    @Override
    public void destroy() {
        if (CollUtil.isNotEmpty(MAP)) {
            MAP.values().forEach((instance) -> ComUtil.uiThreadRun(instance::stopCallback));
        }
        log.info("已销毁{}个窗口实例", MAP.size());
        MAP.clear();
    }

    /**
     * 获取/创建控制器单例（线程安全）
     *
     * @param cls 控制器类型
     * @param <E> 控制器泛型
     * @return 完全初始化的实例
     */
    @SuppressWarnings("unchecked")
    public static <E extends AbstractController> E getInstance(Class<E> cls) {
        // 第一重检查：无锁快速路径
        E instance = (E) MAP.get(cls);
        if (instance == null) {
            synchronized (StageSingletonContext.class) {
                // 第二重检查：避免重复创建
                instance = (E) MAP.get(cls);
                if (instance == null) {
                    instance = (E) EARLY_SINGLETON_MAP.get(cls);
                    if (instance == null) {
                        try {
                            log.debug("开始创建控制器实例: {}", cls.getName());
                            // 阶段1：原始对象创建
                            instance = createRawInstance(cls);
                            // 阶段2：提前暴露引用
                            EARLY_SINGLETON_MAP.put(cls, instance);
                            // 阶段3：完成依赖注入
                            initializeInstance(instance);
                            // 阶段4：移入正式缓存
                            MAP.put(cls, instance);
                            EARLY_SINGLETON_MAP.remove(cls);
                        } catch (Exception e) {
                            EARLY_SINGLETON_MAP.remove(cls);
                            throw new BizException("控制器创建失败: " + cls.getName(), e);
                        }
                    }
                }
            }
        }
        return instance;
    }

    /**
     * 创建原始实例（不触发依赖注入）
     *
     * @param cls 控制器类型
     * @return 未初始化的实例
     */
    private static <E extends AbstractController> E createRawInstance(Class<E> cls) {
        try {
            // 尝试FXML加载（约定优于配置）
            String fxmlName = convertFxmlName(cls);
            URL resource = loadFunction.apply(fxmlName);

            if (resource != null) {
                FXMLLoader fxmlLoader = new FXMLLoader(resource);
                fxmlLoader.load();
                E controller = fxmlLoader.getController();
                // 初始化UI组件
                controller.init(fxmlLoader.getRoot(), true);
                log.debug("通过FXML加载控制器: {}", fxmlName);
                return controller;
            }
            // 反射回退机制
            log.warn("未找到FXML文件，使用反射创建: {}", cls.getName());
            return NewClassGraphUtil.newInstance(cls);
        } catch (Exception e) {
            throw new BizException("控制器实例化失败: " + cls.getName(), e);
        }
    }

    /**
     * 完成实例初始化
     *
     * @param instance 待初始化的实例
     */
    private static <E extends AbstractController> void initializeInstance(E instance) {
        try {
            // 依赖注入处理
            for (Field field : instance.getClass().getDeclaredFields()) {
                if (field.isAnnotationPresent(InjectBean.class)) {
                    field.setAccessible(true);
                    BeanContext beanContext = Assert.notNull(ContextService.getService(BeanContext.class), "未注入BeanContext对象");
                    Object dependency = beanContext.getBean(field.getType());
                    Assert.notNull(dependency, "依赖注入失败: " + field.getType().getName());
                    field.set(instance, dependency);
                    log.debug("已注入依赖: {} => {}", instance.getClass().getSimpleName(), field.getName());
                }
            }
            // 生命周期回调
            instance.runBeforeCallback();
        } catch (Exception e) {
            Assert.throwBizException(e, "初始化失败: {}", instance.getClass().getName());
        }
    }

    /**
     * 移除实例并触发销毁
     *
     * @param cls 要移除的控制器类型
     */
    public static synchronized void removeInstance(Class<? extends AbstractController> cls) {
        AbstractController instance = MAP.get(cls);
        if (instance != null) {
            try {
                // 触发销毁前回调
                instance.stopCallback();
            } catch (Exception e) {
                log.error("实例[{}]销毁异常: {}", cls.getName(), e.getMessage());
            }
            MAP.remove(cls);
            log.info("已移除实例: {}", cls.getName());
        }
    }

    /**
     * 转换FXML文件名规则：
     * 1. 移除类名中的"Controller"后缀
     * 2. 转换为kebab-case格式
     * 示例：MainWindowController -> main-window.fxml
     */
    private static String convertFxmlName(Class<? extends AbstractController> cls) {
        String className = cls.getSimpleName().replace("Controller", "");
        return NamingCase.toKebabCase(className) + ".fxml";
    }

    /**
     * 原有工具方法保留
     */
//    public static synchronized void startupBefore() {
//        if (CollUtil.isNotEmpty(MAP)) {
//            MAP.values().forEach((instance) -> ComUtil.uiThreadRun(instance::runBeforeCallback));
//        }
//    }

}